package core

import (
	"errors"
	"github.com/nats-io/nats.go"
	"openzbox.com/driver/conn/serial"
	"openzbox.com/log"
	"openzbox.com/utils"
)

var (
	NC *nats.Conn
)

/*
type BasicPort struct {
	Type string `json:"type"`
}*/

type PortConfig struct {
	Name   string        `json:"name"`
	Type   string        `json:"type"`
	R120   bool          `json:"r120,omitempty"`
	Booton bool          `json:"booton"`
	Ioctrl string        `json:"ioctrl,omitempty"`
	Opts   serial.Config `json:"opts"`
}

type Callback func(port string, msg []byte)

type Port interface {
	Open(callback Callback) error
	OpenWithOpts(callback Callback, args ...interface{}) error
	SendString(data string) error
	SendBytes(data []byte) error
	Close() error
	GetName() string
	GetType() string
	GetOpts() serial.Config
	SetOpts(serial.Config)
}

func StartNatsConnect() {
	var err error
	NC, err = nats.Connect("nats://127.0.0.1:4222")
	//defer nc.Close()
	if err != nil {
		log.Errorf("nats error: %s", err)
	}
	log.Info("nats connected:", NC.Servers())

}

/*获取单个端口*/
func (box *Mbox) GetPort(name string) (c Port, e error) {
	if utils.IsEmptyString(name) {
		return nil, errors.New("does not exist port:" + name)
	}
	x := box.Ports[name]
	if x == nil {
		return nil, errors.New("does not exist port:" + name)
	}
	return x, nil
}

/*修改端口并返回新对象*/
func (box *Mbox) UpdatePort(port Port) (rport Port, errx error) {
	//fmt.Println(port.GetName())
	box.Ports[port.GetName()] = port
	cfg := box.PortCfgs[port.GetName()]
	cfg.Opts = port.GetOpts()
	box.PortCfgs[port.GetName()] = cfg
	//fmt.Println(box.Ports[port.GetName()])
	_, err := box.SaveConfig()
	if err != nil {
		return nil, err
	}
	return box.GetPort(port.GetName())
}

/*获取所有串口*/
func (mbox *Mbox) ListPorts() (ports map[string]Port) {
	return mbox.Ports
}

/*
func (mbox *Mbox) ListeningAllPorts() error {
	return mbox.Ports
}*/

func (mbox *Mbox) CloseAllPorts() error {
	/*for _, p := range mbox.Ports {
		p.Close()
	}*/
	return nil
}

func (mbox *Mbox) InitPorts() {
	var ports = make(map[string]Port)
	//portconfs := mbox.Portsstr
	log.Infof("init %d ports.", len(mbox.PortCfgs))
	//log.Infof("init %v ports.", mbox.Portsstr)
	for _, poi := range mbox.PortCfgs {
		//po := (*PortConfig)(unsafe.Pointer(&poi)) //poi.(PortConfig)
		//po := poi.(map[string]interface{})
		if poi.Type == "232" {
			//optstr := po["opts"] //.(string)
			p, err := New232Port(poi.Name, poi.Type, poi.Opts)
			if err == nil {
				//ports[po.GetName()] = p
				log.Infof("init %s %v :", p.GetName(), p)
				ports[p.GetName()] = p
			} else {
				log.Errorf("error init port :%v, %s", poi, err.Error())
			}
		} else if poi.Type == "TTL" {
			p, err := New232Port(poi.Name, poi.Type, poi.Opts)
			if err == nil {
				//ports[po.GetName()] = p
				log.Infof("init %s %v :", p.GetName(), p)
				ports[p.GetName()] = p
			} else {
				log.Errorf("error init port :%v, %s", poi, err.Error())
			}
		} else if poi.Type == "485" {
			p, err := New232Port(poi.Name, poi.Type, poi.Opts)
			if err == nil {
				//ports[po.GetName()] = p
				log.Infof("init %s %v :", p.GetName(), p)
				ports[p.GetName()] = p
			} else {
				log.Errorf("error init port :%v, %s", poi, err.Error())
			}
		} else if poi.Type == "CAN" {
			p, err := NewCANPort(poi.Name, poi.Type, poi.Opts)
			if err == nil {
				//ports[po.GetName()] = p
				log.Infof("init %s %v :", p.GetName(), p)
				ports[p.GetName()] = p
			} else {
				log.Errorf("error init port :%v, %s", poi, err.Error())
			}
		}
		//fmt.Println("Index =", "Value =", po["type"])
		/*po := poi.(Port)
		fmt.Println(po)
		p, err := New232Port(po.GetName(), po.GetType(), po.GetOpts())
		if err == nil {
			//ports[po.GetName()] = p
			log.Infof("init %s %v %v:", po.GetName(), po, p)
		} else {
			log.Errorf("error init port :%v, %s", po, err.Error())
		}*/
		//log.Infof(k, poi)
	}
	mbox.Ports = ports
}
